//C10:InnerClassIdiom.cpp
// Example of the "inner class" idiom.
#include <iostream>
#include <locale>
#include <string>
using namespace std;

class Poingable
{
    public:
        virtual void poing() = 0;
};

void callPoing(Poingable& p)
{
    p.poing();
}

class Bingable
{
    public:
        virtual void bing() = 0;
};

void callBing(Bingable& b)
{
    b.bing();
}

class Outer
{
    string name;
    // Define one inner class:
    class Inner1;
    friend class Outer::Inner1;
    class Inner1  : public Poingable
    {
        Outer* parent;
        public:
            Inner1(Outer* p) : parent(p) {}      
            void poing()
            {
                cout << "poing called for "
                     << parent->name << endl;
                // Accesses data int the outer class object     
            }
    } inner1;

    // Define a second inner class:
    class Inner2
    {
        Outer* parent;
        public:
            Inner2(Outer* p) : parent(p) {}
            void bing()
            {
                cout << "bing called for "
                     << parent->name << endl;
            }
    } inner2;
    public:
        Outer(const string& nm)
        : name(nm), inner1(this), inner2(this) {}
        // Return reference to interfaces
        // implemented by the inner classes:
        operator Poingable&() { return inner1; }
        operator Bingable&() { return inner2; }
};

int main(void)
{
    Outer x("Ping Pong");
    // Like upcasting to multiple base types!:
    callPoing(x);
    callBing(x);
}